package Integration;

import MathLib.triangulation.SaveStructures.Node;

class FuncWithJacobian implements IFunction2D{

        protected Node A;
        protected Node B;
        protected Node C;
        protected double S2;

        protected IFunction2D startFunc;
        protected double Jacobian;
        protected double ai ,
                         aj ,
                         ak ;
        protected double bi ,
                         bj ,
                         bk ;
        protected double ci ,
                         cj ,
                         ck ;

        public FuncWithJacobian(Node A, Node B, Node C, IFunction2D startFunc) {
            this.A = A;
            this.B = B;
            this.C = C;
            this.startFunc = startFunc;

            ai = B.x*C.y - C.x*B.y;
            aj = C.x*A.y - A.x*C.y;
            ak = A.x*B.y - B.x*A.y;

            bi = B.y-C.y;
            bj = C.y-A.y;
            bk = A.y-B.y;

            ci = C.x-B.x;
            cj = A.x-C.x;
            ck = B.x-A.x;

            //Jacobian = (  (cj)*(bi) - (ci)*(bj) ) ;

            double a =Math.sqrt( ( ck )*(ck) + (bk)*(bk) );   //a-b
            double b =Math.sqrt( (ci)*(ci) + (bi)*(bi) );
            double c =Math.sqrt( (cj)*(cj) + (bj)*(bj) );
            double p = (a+b+c)/2.0;
            S2 =  Math.sqrt( p*(p-a)*(p-b)*(p-c) )*2;
            Jacobian = S2;

        }

        private double Li(double x, double y){
            return (ai+bi*x+ci*y)/S2;
        }

        private double Lj(double x, double y){
            return (aj+bj*x+cj*y)/S2;
        }

        private double Lk(double x, double y){
            return (aj+bj*x+cj*y)/S2;
        }



        public double calculate(double x, double y) {
            //double li = Li(x, y),
            //       lj = Lj(x, y),
            //       lk = Lk(x, y);
            double li = x,
                   lj = y,
                   lk = 1 -x - y;

            x = li*A.x + lj*B.x + lk*C.x;
            y = li*A.y + lj*B.y + lk*C.y;
            return startFunc.calculate(x, y)*Jacobian;

        }

        public double calculateDerivatyX(double x, double y) {
            double li = Li(x, y),
                   lj = Lj(x, y),
                   lk = Lk(x, y);
            x = li*A.x + lj*B.x + lk*C.x;
            y = li*A.y + lj*B.y + lk*C.y;
            return startFunc.calculateDerivatyX(x, y)*Jacobian;
        }

        public double calculateDerivatyY(double x, double y) {
            double li = Li(x, y),
                   lj = Lj(x, y),
                   lk = Lk(x, y);
            x = li*A.x + lj*B.x + lk*C.x;
            y = li*A.y + lj*B.y + lk*C.y;
            return startFunc.calculateDerivatyY(x, y)*Jacobian;
        }

    }